package com.atguigu.gulimall.product.config;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.io.IOUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;


@Configuration
public class MyRedisConfig {


    // @Bean
    // public RedisCommands<String, String>
    // getStatefulRedisConnection(RedisConnectionFactory redisConnectionFactory)
    // throws Exception {
    // RedisStringCommands client =
    // redisConnectionFactory.getConnection().stringCommands();
    // client.
    // RedisCommands<String, String> connection = client.connect(
    // CompressionCodec.valueCompressor(StringCodec.UTF8,
    // CompressionCodec.CompressionType.GZIP)).sync();
    // return connection;
    // }

    // @Bean
    // public StatefulRedisConnection<String, String> getRedisClient() {
    //     StatefulRedisConnection<String, String> connection = (StatefulRedisConnection<String, String>) redisClient
    //             .connect(CompressionCodec.valueCompressor(StringCodec.UTF8, CompressionCodec.CompressionType.GZIP))
    //             .sync();
    //     return connection;
    // }

    // redis传输前将json进行数据压缩，因为是直接压缩原始数据，
    // 但是会使保存在redis的数据json数据不可读
    @Bean
    public StringRedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(connectionFactory);
        connectionFactory.getConnection().openPipeline();
        // Set a custom serializer that will compress/decompress data to/from redis
        RedisSerializerGzip serializerGzip = new RedisSerializerGzip();
        template.setValueSerializer(serializerGzip);
        template.setHashValueSerializer(serializerGzip);
        return template;
    }

    public class RedisSerializerGzip extends JdkSerializationRedisSerializer {

        @Override
        public Object deserialize(byte[] bytes) {
            if (null == bytes || bytes.length == 0) {
                return null;
            }
            return super.deserialize(decompress(bytes));
        }

        @Override
        public byte[] serialize(Object object) {
            return compress(super.serialize(object));
        }

        ////////////////////////
        // Helpers
        ////////////////////////
        private byte[] compress(byte[] content) {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
                gzipOutputStream.write(content);
            } catch (IOException e) {
                throw new SerializationException("Unable to compress data", e);
            }
            return byteArrayOutputStream.toByteArray();
        }

        private byte[] decompress(byte[] contentBytes) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                IOUtils.copy(new GZIPInputStream(new ByteArrayInputStream(contentBytes)), out);
            } catch (IOException e) {
                throw new SerializationException("Unable to decompress data", e);
            }
            return out.toByteArray();
        }

    }
}
